<template>
  <div class="container">
    <div class="title">一类级配计算器: <el-button @click="openHistory">历史</el-button></div>
    <div class="s-title">
      选择种类:
      <div class="tools">
        <el-input-number v-model="dataSize" :min="1" />
      </div>
    </div>

    <div class="s-title">正常指标范围:</div>
    <div class="list">
      <div v-for="item in dataSize" :key="item" class="item">
        <div class="item-title">
          <el-input v-model="mu[item]" class="item-input">
            <template #append>目</template>
          </el-input>
        </div>
        <div class="item-content">
          <el-input v-model="downMu[item]" style="width: 70px" class="item-input" />
          ~
          <el-input v-model="upMu[item]" style="width: 70px" class="item-input" />
        </div>
      </div>
    </div>
    <!-- 提示0-100，“输入错误” -->
    <!-- 逐次减小 -->

    <div class="s-title">主批次粒度X:</div>
    <div class="list">
      <div v-for="item in dataSize" :key="item" class="item">
        <el-input
          v-model="primary[item]"
          style="width: 70px"
          class="item-input"
          @change="validatePrimary(item)"
        />
      </div>
    </div>
    <div>
      <el-button size="small" type="info" :disabled="isDisabled" @click="secondaryTest">
        配合范围测试
      </el-button>
    </div>
    <div class="s-title">
      配合范围:
      <el-input
        v-model="coordinationRangeDown"
        style="width: 70px"
        class="item-input"
        @input="changeCoordinationRange"
      />
      ~
      <el-input
        v-model="coordinationRangeUp"
        style="width: 70px"
        class="item-input"
        @input="changeCoordinationRange"
      />
    </div>
    <div class="list">
      <div v-for="item in dataSize" :key="item" class="item">
        <div class="item-content">
          <el-input v-model="secondaryDown[item]" style="width: 70px" class="item-input" />
          ~
          <el-input v-model="secondaryUp[item]" style="width: 70px" class="item-input" />
        </div>
      </div>
    </div>

    <div class="s-title">副批次粒度Y:</div>
    <div class="list">
      <div v-for="item in dataSize" :key="item" class="item">
        <el-input v-model="secondary[item]" style="width: 70px" class="item-input" />
      </div>
    </div>
    <!-- 存储成功数据 -->
    <el-button class="test-btn" type="info" @click="test">计算</el-button>
    <hr />
    <!-- 只要有交集就为红色 -->
    <!-- 四个有交集为绿色，三个或两个改为红色底色 -->
    <div class="s-title">
      配合系数a范围:
      <el-button size="small" type="info" style="float: right" @click="copyList('ratio')">
        复制一行数据
      </el-button>
    </div>
    <div class="list">
      <div v-for="item in dataSize" :key="item" class="item">
        <div class="flex">
          <div class="flex-1" @click="copy(downRatio[item])">
            <div>下限</div>
            <div class="h-20">{{ downRatio[item] }}</div>
          </div>
          <div class="flex-1" @click="copy(upRatio[item])">
            <div>上限</div>
            <div class="h-20">{{ upRatio[item] }}</div>
          </div>
        </div>
      </div>
    </div>
    <div class="s-title">
      综合配合系数范围:
      <el-button size="small" type="info" style="float: right" @click="copyList('inputData')">
        复制一行数据
      </el-button>
    </div>
    <div class="list">
      <div class="item" @click="copy(inputData.down)">下限：{{ inputData.down }}</div>
      <div class="item" @click="copy(inputData.up)">上限：{{ inputData.up }}</div>
      <div class="item" style="width: 300px" @click="copy(inputData.most)">
        最佳配合系数: {{ inputData.most }}
      </div>
    </div>
    <div class="s-title">
      混合批次粒度:
      <el-button size="small" type="info" style="float: right" @click="copyList('mix')">复制一行数据</el-button>
    </div>
    <div class="list">
      <div v-for="item in dataSize" :key="item" class="item h-30" @click="copy(mix[item])">
        {{ mix[item] }}
      </div>
    </div>
    <el-dialog v-model="tableVisible" title="历史记录" destroy-on-close width="600">
      <HistoryList @recover="recover" />
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onBeforeMount, watch, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import Decimal from 'decimal.js'
import { db } from './utils/db.js'
import HistoryList from './components/HistoryList.vue'
const tableVisible = ref(false)

const dataSize = ref(4) //决定有多少个数据
// 综合配合系数范围上下限以及最佳配合系数
const inputData = reactive({
  up: '',
  down: '',
  most: ''
})

const mu = ref({}) // 目
const downMu = ref({}) // 目下限
const upMu = ref({}) // 目上限

// const primary = reactive({ 1: '100', 2: '95', 3: '82', 4: '20' }) // 主批次粒度X
const primary = reactive({})
// 配合范围上下限
const secondaryUp = ref({})
const secondaryDown = ref({})
const coordinationRangeDown = ref()
const coordinationRangeUp = ref()

const secondary = reactive({}) // 副批次粒度Y

const mix = reactive([]) // 混合批次粒度
const downRatio = reactive({}) // 配合系数a范围下限
const upRatio = reactive({}) // 配合系数a范围上限

const isDisabled = ref(true)

// 复制一行数据
const copy = (text) => {
  const textArea = document.createElement('textarea')
  textArea.value = text
  document.body.appendChild(textArea)
  textArea.focus()
  textArea.select()
  try {
    document.execCommand('copy')
    ElMessage.success('复制成功')
  } catch (error) {
    ElMessage.warning('复制失败')
  }
  document.body.removeChild(textArea)
}

const copyList = (title) => {
  if (title === 'ratio') {
    let ratioTextArray = []
    for (let i = 1; i <= dataSize.value; i++) {
      ratioTextArray.push(downRatio[i], upRatio[i])
    }
    let ratioText = ratioTextArray.join(',')
    copy(ratioText)
    console.log(ratioText)
  } else if (title === 'inputData') {
    let inputDataTextArray = []
    inputDataTextArray.push(
      inputData.down.toString(),
      inputData.up.toString(),
      inputData.most.toString()
    )
    let inputDataText = inputDataTextArray.join(',')
    console.log(inputDataText)
  } else if (title === 'mix') {
    let mixTextArray = []
    for (let i = 1; i <= dataSize.value; i++) {
      mixTextArray.push(mix[i])
    }
    let mixText = mixTextArray.join(',')
    copy(mixText)
    console.log(mixText)
  }
}

// 在组件挂载前检查localStorage
onBeforeMount(() => {
  getData()
})

// 监听dataSize数据变化
watch(dataSize, () => {
  getData()
})

const changeCoordinationRange = () => {
  if (coordinationRangeDown.value !== undefined && coordinationRangeUp.value !== undefined) {
    isDisabled.value = false
  } else {
    isDisabled.value = true
  }
}

const test = () => {
  // 存储数据
  localStorage.setItem('mu', JSON.stringify(mu.value))
  localStorage.setItem('downMu', JSON.stringify(downMu.value))
  localStorage.setItem('upMu', JSON.stringify(upMu.value))
  let y = 0.001

  // 根据dataSize选择数组值，存放配合系数
  const value = {}
  for (let i = 1; i <= dataSize.value; i++) {
    value[i] = []
  }

  // y从0.01到10筛选在比例中的配合系数
  for (let i = 0; ; i++) {
    let t = 1
    for (t = 1; t <= dataSize.value; t++) {
      let b = new Decimal(y)
        .mul(new Decimal(secondary[t]))
        .add(new Decimal(primary[t]))
        .div(new Decimal(y).add(new Decimal(1)))
      let a = b.gt(downMu.value[t]) && b.lt(upMu.value[t]) // 使用 Decimal.js 提供的比较方法 gt() 和 lt()
      if (a) {
        value[t].push(y)
      }
    }
    y = new Decimal(y).add(new Decimal(0.001)).toString() // y += 0.01
    if (new Decimal(y).equals(new Decimal(10))) {
      break
    }
  }

  // 综合配合系数
  let valueAll = []
  const isValue = ref()

  for (let i = 1; i <= value[1].length; i++) {
    // 检查其他三个数组是否包含相同的元素
    let element = value[1][i]
    isValue.value = true
    for (let j = 2; j <= Object.keys(value).length; j++) {
      isValue.value = value[j].includes(element) && isValue.value
    }
    if (isValue.value) {
      valueAll.push(element)
    }
  }

  // 综合配合系数最小值
  let down = new Decimal(Math.min(...valueAll)).add(new Decimal(0.01))
  if (0 < down && down <= 10) {
    inputData.down = down
  } else {
    inputData.down = ''
  }

  // 综合配合系数最大值
  let up = new Decimal(Math.max(...valueAll)).sub(new Decimal(0.01))
  if (0 < up && up <= 10) {
    inputData.up = up
  } else {
    inputData.up = ''
  }

  for (let i = 1; i <= dataSize.value; i++) {
    // 配合系数a最小值
    let min = Math.min(...value[i])
    if (0 <= min && min <= 10) {
      downRatio[i] = min.toFixed(2)
    } else {
      downRatio[i] = ''
    }
    // 配合系数a最大值
    let max = Math.max(...value[i])
    if (0 <= max && max <= 10) {
      upRatio[i] = max.toFixed(2)
    } else {
      upRatio[i] = ''
    }
  }

  // 混合批次粒度
  mixAll()

  nextTick(() => {
    // 所有数据集合做存储
    const obj = {
      dataSize: dataSize.value,
      inputData: inputData,
      mu: mu.value,
      downMu: downMu.value,
      upMu: upMu.value,
      primary: primary,
      secondaryUp: secondaryUp.value,
      secondaryDown: secondaryDown.value,
      secondary: secondary,
      mix: mix,
      downRatio: downRatio,
      upRatio: upRatio
    }
    // db.items.add({ name: `Another item` })
    db.items.add({ name: JSON.stringify(obj), description: '', stamptime: new Date().getTime() })
  })
}

// 回顾记录
const recover = (obj) => {
  dataSize.value = obj.dataSize

  Object.keys(obj.inputData).forEach((key) => {
    inputData[key] = obj.inputData[key]
  })

  tableVisible.value = false
  mu.value = obj.mu
  downMu.value = obj.downMu
  upMu.value = obj.upMu

  Object.keys(obj.primary).forEach((key) => {
    primary[key] = obj.primary[key]
  })

  secondaryUp.value = obj.secondaryUp
  secondaryDown.value = obj.secondaryDown

  Object.keys(obj.secondary).forEach((key) => {
    secondary[key] = obj.secondary[key]
  })

  Object.keys(obj.mix).forEach((key) => {
    mix[key] = obj.mix[key]
  })

  Object.keys(obj.downRatio).forEach((key) => {
    downRatio[key] = obj.downRatio[key]
  })

  Object.keys(obj.upRatio).forEach((key) => {
    upRatio[key] = obj.upRatio[key]
  })
}

const openHistory = () => {
  tableVisible.value = true
}

// 取仓库数据
const getData = () => {
  const storedMu = localStorage.getItem('mu')
  const storedDownMu = localStorage.getItem('downMu')
  const storedUpMu = localStorage.getItem('upMu')

  if (storedMu && storedDownMu && storedUpMu) {
    // 如果localStorage中有值且数量与dataSize相同，则赋值给对应变量
    const parsedMu = JSON.parse(storedMu)
    const parsedDownMu = JSON.parse(storedDownMu)
    const parsedUpMu = JSON.parse(storedUpMu)

    if (
      Object.keys(parsedMu).length === dataSize.value &&
      Object.keys(parsedDownMu).length === dataSize.value &&
      Object.keys(parsedUpMu).length === dataSize.value
    ) {
      mu.value = parsedMu
      downMu.value = parsedDownMu
      upMu.value = parsedUpMu
    } else {
      mu.value = {}
      downMu.value = {}
      upMu.value = {}
    }
  }
}

// 验证主批次粒度
const validatePrimary = (item) => {
  if (primary[item == '']) {
    ElMessage.error('不能为空')
  } else if (
    new Decimal(primary[item]).lt(new Decimal(0)) ||
    new Decimal(primary[item]).gt(new Decimal(100))
  ) {
    ElMessage.error('请输入0~100的数字')
    primary[item] = ''
  } else {
    if (item > 1) {
      if (new Decimal(primary[item]).gt(new Decimal(primary[item - 1]))) {
        ElMessage.error('请输入逐次递减的数据')
        primary[item] = ''
      }
    }
  }
}

// 根据主批次粒度得出配合范围
const secondaryTest = () => {
  const calculateSecondary = (primary, mu, range) => {
    let a = new Decimal(mu).div(new Decimal(range))
    let b = new Decimal(mu).sub(new Decimal(primary).div(range))
    return new Decimal(a).add(new Decimal(b))
  }

  // 配合粒度的筛选
  const secondaryMin = []
  for (let i = 1; i <= dataSize.value; i++) {
    secondaryMin[i] = 101
  }
  const secondaryMax = []
  for (let i = 1; i <= dataSize.value; i++) {
    secondaryMax[i] = 0
  }

  let z = coordinationRangeDown.value
  for (let i = 0; ; i++) {
    let t = 1
    for (t = 1; t <= dataSize.value; t++) {
      let a = calculateSecondary(primary[t], downMu.value[t], z).toFixed(1)

      if (new Decimal(a).lt(new Decimal(secondaryMin[t])) && new Decimal(a).gt(new Decimal(0))) {
        secondaryMin[t] = a
      }
      let b = calculateSecondary(primary[t], upMu.value[t], z).toFixed(1)
      if (new Decimal(b).gt(new Decimal(secondaryMax[t])) && new Decimal(a).lt(new Decimal(100))) {
        secondaryMax[t] = b
      }
    }
    z = new Decimal(z).add(new Decimal(0.001)).toString() // z += 0.01
    if (z > coordinationRangeUp.value) {
      break
    }
  }
  secondaryDown.value = secondaryMin.map((item) => {
    if (0 < item && item < 100) {
      return item
    } else {
      return 'null'
    }
  })
  secondaryUp.value = secondaryMax.map((item) => {
    if (0 < item && item < 100) {
      return item
    } else {
      return 'null'
    }
  })
}

// 混合批次粒度
const mixAll = () => {
  const calculateMix = (primary, secondary) => {
    if (inputData.down && inputData.up) {
      const a = new Decimal(secondary).add(
        new Decimal(primary)
          .sub(new Decimal(secondary))
          .div(new Decimal(inputData.down).add(new Decimal(1)))
      )
      const b = new Decimal(secondary).add(
        new Decimal(primary)
          .sub(new Decimal(secondary))
          .div(new Decimal(inputData.up).add(new Decimal(1)))
      )
      return new Decimal(a).add(new Decimal(b)).div(2)
    } else {
      return ''
    }
  }

  for (let i = 1; i <= dataSize.value; i++) {
    if (calculateMix(primary[i], secondary[i]) == '') {
      mix[i] = ''
    } else {
      mix[i] = calculateMix(primary[i], secondary[i]).toFixed(2)
    }
  }

  const sub = ref(0)
  for (let i = 1; i <= 4; i++) {
    if (calculateMix(primary[i], secondary[i]) == '') {
      sub.value = ''
    } else {
      let a = new Decimal(calculateMix(primary[i], secondary[i])).sub(new Decimal(primary[i]))
      let b = new Decimal(secondary[i]).sub(new Decimal(calculateMix(primary[i], secondary[i])))
      let c = new Decimal(a).div(new Decimal(b)).toFixed(3)
      sub.value = new Decimal(sub.value).add(new Decimal(c))
    }
  }

  if (sub.value == '') {
    inputData.most = ''
  } else {
    let most = new Decimal(sub.value).div(new Decimal(4))
    if (0 <= most && most <= 10) {
      inputData.most = most
    } else {
      inputData.most = ''
    }
  }
}
</script>

<style scope>
.flex {
  display: flex;
}
.flex-1 {
  flex: 1;
}
.container {
  width: 100%;
  height: 100%;
  background-color: #f5f7fa;
  padding: 0 10px;
  margin: auto;
  color: #272727;
  overflow-x: auto;
  font-size: 18px;
}
.title {
  font-size: 18px;
  font-weight: bolder;
  text-align: center;
  color: #4a4a4a;
}
.s-title {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 5px;
  color: #4a4a4a;
}
.tools {
  display: inline-block;
}
.list {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
.item {
  width: calc(25% - 10px);
  padding: 5px;
  background-color: #ffffff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  border-radius: 5px;
  text-align: center;
  margin-bottom: 10px;
  font-size: 15px;
}
.changeClass {
  background-color: #ffdddd;
}
.item-title {
  margin-bottom: 5px;
  color: #666;
}

.item-input {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}
.h-20 {
  height: 20px;
}
.h-30 {
  height: 30px;
}
.item-input .el-input__inner {
  text-align: center;
  font-size: 18px;
}
.item-input .el-input-group__append {
  border: unset;
  border-left: 1px solid #dcdfe6;
  box-shadow: unset;
}
.test-btn {
  width: 100%;
  height: 40px;
  font-size: 18px;
  background-color: #409eff;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>
